package org.maylove.wuziqi.game;

import org.maylove.wuziqi.common.EventMessage;
import org.maylove.wuziqi.pojo.game.dto.GameNoGameDto;
import org.maylove.wuziqi.pojo.game.dto.GameNoStartDto;
import org.maylove.wuziqi.timer.TimerService;
import org.springframework.context.ApplicationEventPublisher;

public class GameRoom {

    //  设置长时间不开游戏被踢的时间（单位：秒）
    private static final Integer PREPARE_TIME = 30 * 60  ;
    //  设置每次游戏的下子被踢的时间（单位：秒）
    private static final Integer GAME_TIME = 60;

    private Long player1;               //  玩家一id
    private Long player2;               //  玩家二id
    private Integer[][] board;          //  棋盘
    private Boolean waitPlay1;          //  玩家一准备状态
    private Boolean waitPlay2;          //  玩家二准备状态
    private Integer waitPlayer;         //  轮到谁下棋
    private TimerService timer;         //  计时器
    private Integer roomId;             //  房间id
    private ApplicationEventPublisher applicationEventPublisher;    //  推送事件
    private Integer lastX;
    private Integer lastY;

    public GameRoom(ApplicationEventPublisher applicationEventPublisher) {
        board = new Integer[16][16];
        player1 = null;
        player2 = null;
        this.applicationEventPublisher = applicationEventPublisher;
    }

    public void initRoom() {
        for (int i = 0; i < 16; i++) {
            for (int j = 0; j < 16; j++) {
                board[i][j] = 0;
            }
        }
        waitPlay1 = false;
        waitPlay2 = false;
        waitPlayer = 1;
        timer = new TimerService(applicationEventPublisher);
        lastX = 0;
        lastY = 0;
        waitStart();
    }

    public void waitStart() {
        timer.cancelEvent();
        EventMessage message = new EventMessage();
        GameNoStartDto gameNoStartDto = new GameNoStartDto();
        gameNoStartDto.setRoomId(roomId);
        message.setData(gameNoStartDto);
        message.setMsg("Players in the room do not start playing for a long time!");
        timer.scheduleEvent(PREPARE_TIME, message);
    }

    private void waitGame() {
        timer.cancelEvent();
        EventMessage message = new EventMessage();
        GameNoGameDto gameNoGameDto = new GameNoGameDto();
        gameNoGameDto.setRoomId(this.roomId);
        if(waitPlayer == 1) gameNoGameDto.setUserId(player1);
        else gameNoGameDto.setUserId(player2);
        message.setData(gameNoGameDto);
        message.setMsg("Players do not play for a long time!");
        timer.scheduleEvent(GAME_TIME, message);
    }

    public String prepare(int player) {
        if(player == 1) {
            if(waitPlay1) {
                return "The player is ready!";
            }
            else {
                waitPlay1 = true;
                if(waitPlay2) {
                    startGame();
                }
                return "success";
            }
        }
        else {
            if(waitPlay2) {
                return "The player is ready!";
            }
            else {
                waitPlay2 = true;
                if(waitPlay1) {
                    startGame();
                }
                return "success";
            }
        }
    }

    private void startGame() {
        waitGame();
    }

    private String win(int player) {
        timer.cancelEvent();
        return "win";
    }

    public String game(int player, Integer x, Integer y) {
        //  判断是否该玩家落子
        if(player != waitPlayer) return "It's not the player's turn to play chess!";

        //  判断落子位置是否有棋
        if(board[x][y] != 0) return "There are already chess pieces in this position!";

        //  TODO:判断三三禁手

        //  下棋
        board[x][y] = player;
        lastX = x;
        lastY = y;
        waitPlayer = 3 - waitPlayer;
        waitGame();
        //  判胜
        int tmpx, tmpy;
        int mx = 1;
        tmpx = x - 1; tmpy = y; while(tmpx > 0 && board[tmpx][tmpy] == player) {tmpx--; mx++;}
        tmpx = x + 1; tmpy = y; while(tmpx < 16 && board[tmpx][tmpy] == player) {tmpx++; mx++;}
        if(mx >= 5) return win(player); mx = 1;

        tmpx = x; tmpy = y - 1; while(tmpy > 0 && board[tmpx][tmpy] == player) {tmpy--; mx++;}
        tmpx = x; tmpy = y + 1; while(tmpy < 16 && board[tmpx][tmpy] == player) {tmpy++; mx++;}
        if(mx >= 5) return win(player); mx = 1;

        tmpx = x - 1; tmpy = y - 1; while(tmpx > 0 && tmpy > 0 && board[tmpx][tmpy] == player) {tmpx--; tmpy--; mx++;}
        tmpx = x + 1; tmpy = y + 1; while(tmpx < 16 && tmpy < 16 && board[tmpx][tmpy] == player) {tmpx++; tmpy++; mx++;}
        if(mx >= 5) return win(player); mx = 1;

        tmpx = x - 1; tmpy = y + 1; while(tmpx > 0 && tmpy < 16 && board[tmpx][tmpy] == player) {tmpx--; tmpy++; mx++;}
        tmpx = x + 1; tmpy = y - 1; while(tmpx < 16 && tmpy > 0 && board[tmpx][tmpy] == player) {tmpx++; tmpy--; mx++;}
        if(mx >= 5) return win(player);

        return "success";
    }

    public String back(int player) {
        if(waitPlayer == player) return "Players have no right to regret their actions!";
        if(lastX == 0 || lastY == 0) return "The player has not played chess yet!";
        board[lastX][lastY] = 0;
        waitPlayer = 3-waitPlayer;
        int tmpX = lastX, tmpY = lastY;
        lastX = 0;
        lastY = 0;
        return "back" + String.format("%02d", tmpX) + String.format("%02d", tmpY);
    }

    public String giveUp(int player) {
        timer.cancelEvent();
        return "success";
    }

    public void free() {
        timer.cancelEvent();
    }


    public Long getPlayer1() {
        return player1;
    }

    public void setPlayer1(Long player1) {
        this.player1 = player1;
    }

    public Long getPlayer2() {
        return player2;
    }

    public void setPlayer2(Long player2) {
        this.player2 = player2;
    }

    public Integer[][] getBoard() {
        return board;
    }

    public void setBoard(Integer[][] board) {
        this.board = board;
    }

    public Boolean getWaitPlay1() {
        return waitPlay1;
    }

    public void setWaitPlay1(Boolean waitPlay1) {
        this.waitPlay1 = waitPlay1;
    }

    public Boolean getWaitPlay2() {
        return waitPlay2;
    }

    public void setWaitPlay2(Boolean waitPlay2) {
        this.waitPlay2 = waitPlay2;
    }

    public Integer getWaitPlayer() {
        return waitPlayer;
    }

    public void setWaitPlayer(Integer waitPlayer) {
        this.waitPlayer = waitPlayer;
    }

    public TimerService getTimer() {
        return timer;
    }

    public void setTimer(TimerService timer) {
        this.timer = timer;
    }

    public Integer getRoomId() {
        return roomId;
    }

    public void setRoomId(Integer roomId) {
        this.roomId = roomId;
    }

    public ApplicationEventPublisher getApplicationEventPublisher() {
        return applicationEventPublisher;
    }

    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        this.applicationEventPublisher = applicationEventPublisher;
    }

    public Integer getLastX() {
        return lastX;
    }

    public void setLastX(Integer lastX) {
        this.lastX = lastX;
    }

    public Integer getLastY() {
        return lastY;
    }

    public void setLastY(Integer lastY) {
        this.lastY = lastY;
    }
}
